{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 参数管理"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "• 访问参数，用于调试、诊断和可视化；\n",
    "\n",
    "• 参数初始化；\n",
    "\n",
    "• 在不同模型组件间共享参数。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[-0.3767],\n",
       "        [-0.2568]], grad_fn=<AddmmBackward0>)"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import torch\n",
    "from torch import nn\n",
    "net=nn.Sequential(nn.Linear(4,8),nn.ReLU(),nn.Linear(8,1))\n",
    "X=torch.rand(2,4)\n",
    "net(X)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 1.参数访问"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "通过Sequential类定义模型时，我们可以通过索引来访问模型的任意层。</br>这\n",
    "就像模型是一个列表一样，每层的参数都在其属性中。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "OrderedDict([('weight', tensor([[-0.3525, -0.0243, -0.0440, -0.2717,  0.0082,  0.1302,  0.2297,  0.1795]])), ('bias', tensor([-0.1387]))])\n"
     ]
    }
   ],
   "source": [
    "\"\"\"检查第二个全连接层的参数,（8，1）\"\"\"\n",
    "print(net[2].state_dict())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'torch.nn.parameter.Parameter'>\n",
      "Parameter containing:\n",
      "tensor([-0.1387], requires_grad=True)\n",
      "tensor([-0.1387])\n"
     ]
    }
   ],
   "source": [
    "print(type(net[2].bias))\n",
    "print(net[2].bias)\n",
    "print(net[2].bias.data)#获取数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "net[2].weight.grad==True#由于没有使用反向传播，所以参数梯度处于初始状态"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[('0.weight',\n",
       "  tensor([[-0.2458,  0.2406, -0.0374,  0.3810],\n",
       "          [ 0.3296, -0.0680, -0.0314,  0.2881],\n",
       "          [-0.2639, -0.3204,  0.1547, -0.3707],\n",
       "          [ 0.4702, -0.4020,  0.4196, -0.4907],\n",
       "          [ 0.2321, -0.0503,  0.4115, -0.0575],\n",
       "          [ 0.1443, -0.4317,  0.1656,  0.3929],\n",
       "          [ 0.3900,  0.0249,  0.2222, -0.4264],\n",
       "          [ 0.2729,  0.3142, -0.3484,  0.1224]])),\n",
       " ('0.bias',\n",
       "  tensor([ 0.3249, -0.4020, -0.0362, -0.3033, -0.3514, -0.3131, -0.1169, -0.3824])),\n",
       " ('2.weight',\n",
       "  tensor([[-0.3525, -0.0243, -0.0440, -0.2717,  0.0082,  0.1302,  0.2297,  0.1795]])),\n",
       " ('2.bias', tensor([-0.1387]))]"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "\"\"\"访问所有参数\"\"\"\n",
    "#等同于net.state_dict()\n",
    "[(name, param.data) for name, param in net.named_parameters()]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[-0.3525, -0.0243, -0.0440, -0.2717,  0.0082,  0.1302,  0.2297,  0.1795]])"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "net.state_dict()['2.weight'].data#访问全连接层的权重"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**从嵌套块收集参数**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "让我们看看，如果我们将多个块相互嵌套，参数命名约定是如何工作的。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[0.4181],\n",
       "        [0.4181]], grad_fn=<AddmmBackward0>)"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def block1():\n",
    "    return nn.Sequential(nn.Linear(4,8),nn.ReLU(),\n",
    "                  nn.Linear(8,4),nn.ReLU())\n",
    "\n",
    "def block2():\n",
    "    net=nn.Sequential()\n",
    "    for i in range(4):\n",
    "        #在这里嵌套\n",
    "        net.add_module(f'block{i}',block1())#子模块名称，添加的块\n",
    "    return net\n",
    "\n",
    "rgnet=nn.Sequential(block2(),nn.Linear(4,1))\n",
    "rgnet(X)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Sequential(\n",
      "  (0): Sequential(\n",
      "    (block0): Sequential(\n",
      "      (0): Linear(in_features=4, out_features=8, bias=True)\n",
      "      (1): ReLU()\n",
      "      (2): Linear(in_features=8, out_features=4, bias=True)\n",
      "      (3): ReLU()\n",
      "    )\n",
      "    (block1): Sequential(\n",
      "      (0): Linear(in_features=4, out_features=8, bias=True)\n",
      "      (1): ReLU()\n",
      "      (2): Linear(in_features=8, out_features=4, bias=True)\n",
      "      (3): ReLU()\n",
      "    )\n",
      "    (block2): Sequential(\n",
      "      (0): Linear(in_features=4, out_features=8, bias=True)\n",
      "      (1): ReLU()\n",
      "      (2): Linear(in_features=8, out_features=4, bias=True)\n",
      "      (3): ReLU()\n",
      "    )\n",
      "    (block3): Sequential(\n",
      "      (0): Linear(in_features=4, out_features=8, bias=True)\n",
      "      (1): ReLU()\n",
      "      (2): Linear(in_features=8, out_features=4, bias=True)\n",
      "      (3): ReLU()\n",
      "    )\n",
      "  )\n",
      "  (1): Linear(in_features=4, out_features=1, bias=True)\n",
      ")\n"
     ]
    }
   ],
   "source": [
    "\"\"\"网络结构:四个隐藏层+1全连接层\n",
    "(4,8)(8,4)=>(4,8)(8,4)=>(4,8)(8,4)=>(4,8)(8,4)===>(4,1)\n",
    "\"\"\"\n",
    "print(rgnet)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([ 0.2664,  0.2722,  0.1644, -0.3165, -0.2036, -0.0280, -0.2713,  0.2220])"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#第一个主要的块，第二个子块，第一层的偏置\n",
    "rgnet[0][1][0].bias.data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "OrderedDict([('weight', tensor([[ 0.3399, -0.1162, -0.2898, -0.3579]])),\n",
       "             ('bias', tensor([0.4452]))])"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#（第二个块）最后全连接层的参数\n",
    "rgnet[1].state_dict()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 参数初始化"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**内置初始化**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(tensor([[ 0.6787, -0.6332,  1.1044,  1.1078],\n",
       "         [ 0.9310, -2.1902, -0.5626,  0.8202],\n",
       "         [-0.3762, -1.1418,  0.1014,  1.5620],\n",
       "         [-0.0630,  0.7076, -0.1404,  0.5394],\n",
       "         [-0.6107,  1.1650, -0.0291,  0.2849],\n",
       "         [ 1.0478, -0.7544,  1.6091,  1.5434],\n",
       "         [-0.2486, -0.4298, -0.1484,  0.8992],\n",
       "         [-1.2068, -0.3766,  1.1558,  1.5088]]),\n",
       " tensor([0., 0., 0., 0., 0., 0., 0., 0.]))"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def init_normal(m):\n",
    "    if type(m)==nn.Linear:\n",
    "        nn.init.normal_(m.weight,mean=0,std=1)#初始化为高斯分布\n",
    "        nn.init.zeros_(m.bias)\n",
    "net.apply(init_normal)\n",
    "net[0].weight.data,net[0].bias.data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [],
   "source": [
    "# #初始化为常数\n",
    "# def init_constant(m):\n",
    "#     if type(m)==nn.Linear:\n",
    "#         nn.init.constant_(m.weight,1)\n",
    "#         nn.init.constant_(m.bias,0.666)\n",
    "# net.apply(init_constant)\n",
    "# net[0].weight.data,net[0].bias.data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Sequential(\n",
      "  (0): Linear(in_features=4, out_features=8, bias=True)\n",
      "  (1): ReLU()\n",
      "  (2): Linear(in_features=8, out_features=1, bias=True)\n",
      ")\n"
     ]
    }
   ],
   "source": [
    "print(net)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**使用Xavier初始化**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "OrderedDict([('weight', tensor([[ 0.6787, -0.6332,  1.1044,  1.1078],\n",
      "        [ 0.9310, -2.1902, -0.5626,  0.8202],\n",
      "        [-0.3762, -1.1418,  0.1014,  1.5620],\n",
      "        [-0.0630,  0.7076, -0.1404,  0.5394],\n",
      "        [-0.6107,  1.1650, -0.0291,  0.2849],\n",
      "        [ 1.0478, -0.7544,  1.6091,  1.5434],\n",
      "        [-0.2486, -0.4298, -0.1484,  0.8992],\n",
      "        [-1.2068, -0.3766,  1.1558,  1.5088]])), ('bias', tensor([0., 0., 0., 0., 0., 0., 0., 0.]))])\n",
      "OrderedDict([('weight', tensor([[42., 42., 42., 42., 42., 42., 42., 42.]])), ('bias', tensor([0.]))])\n"
     ]
    }
   ],
   "source": [
    "def xavier_init(m):\n",
    "    if type(xavier_init)==nn.Linear:\n",
    "        nn.init.xavier_uniform_(m.weight)\n",
    "def init_42(m):\n",
    "    if type(m)==nn.Linear:\n",
    "        nn.init.constant_(m.weight,42)\n",
    "#第一层使用xavier初始化，输出层使用常数初始化\n",
    "net[0].apply(xavier_init)\n",
    "net[2].apply(init_42)\n",
    "print(net[0].state_dict())\n",
    "print(net[2].state_dict())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**自定义初始化**"
   ]
  },
  {
   "attachments": {
    "image.png": {
     "image/png": "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"
    }
   },
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![20250118.png](attachment:image.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[-8.3654,  7.6090, -0.0000,  9.5655],\n",
       "        [-9.8045, -0.0000, -0.0000, -0.0000],\n",
       "        [ 0.0000,  0.0000,  0.0000,  0.0000],\n",
       "        [-5.0570, -0.0000,  7.1555, -5.0490],\n",
       "        [ 0.0000,  0.0000,  0.0000,  0.0000],\n",
       "        [-8.6003, -0.0000, -0.0000,  7.4427],\n",
       "        [ 0.0000, -6.5632, -0.0000,  0.0000],\n",
       "        [-8.2048, -5.4971,  0.0000, -0.0000]])"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def mu_init(m):\n",
    "    if type(m)==nn.Linear:\n",
    "        nn.init.uniform_(m.weight,-10,10)#均匀分布-10到10\n",
    "        m.weight.data*=m.weight.data.abs()>=5#把绝对值大于五的布尔值设为1 ，否则是0，乘以这个数\n",
    "\n",
    "net.apply(mu_init)\n",
    "net[0].weight.data"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**权重共享**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([True, True, True, True, True, True, True, True])\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "tensor([ 6.6660e+03,  3.2672e-01, -1.3385e-01, -3.1296e-01,  2.4043e-01,\n",
       "         2.7597e-01, -1.0531e-01,  2.0741e-01])"
      ]
     },
     "execution_count": 40,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "\"\"\"nn.ReLU()也算层数！！\"\"\"\n",
    "shared=nn.Linear(8,8)\n",
    "net=nn.Sequential(nn.Linear(4,8),nn.ReLU(),\n",
    "                  shared,nn.ReLU(),\n",
    "                  shared,nn.ReLU(),\n",
    "                  nn.Linear(8,1))\n",
    "net(X)\n",
    "#检查参数是否相同\n",
    "print(net[2].weight.data[0]==net[4].weight.data[0])\n",
    "#结果表明，net[2]和net[4]是同一个对象，而并非单纯值相等\n",
    "net[2].weight.data[0,0]=6666\n",
    "net[4].weight.data[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([True, True, True, True, True, True, True, True])\n"
     ]
    }
   ],
   "source": [
    "print(net[2].weight.data[0]==net[4].weight.data[0])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "DL_pytorch",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
